package com.leung.tcpServer;



import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.leung.domain.entity.DeviceConfig;
import com.leung.service.IDeviceConfigService;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class NettyServer {

    @Resource
    private IDeviceConfigService deviceConfigService;

    private final Map<String, Channel> channelMap = new ConcurrentHashMap<>();

    @PostConstruct
    public void start() {
        // 连接线程池
        EventLoopGroup boss = new NioEventLoopGroup(3);

        // 读写线程池
        EventLoopGroup worker = new NioEventLoopGroup(8);

        // 服务器端启动器 -> 负责组装 netty 组件 -> 启动
        try {
            new ServerBootstrap()
                    .group(boss, worker)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel channel) throws Exception {
                            channel.pipeline().addLast(new StringDecoder());
                            channel.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                                @Override
                                public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                    log.debug("接收到的消息:{}",msg);
                                    Map<String ,String> map = JSON.to(Map.class, msg);
                                    DeviceConfig deviceConfig = BeanUtil.fillBeanWithMap(map, new DeviceConfig(), true);
                                    deviceConfigService.updateById(deviceConfig);
                                }
                            });
                        }
                    })
                    .bind(6000)
                    .sync(); // 确保绑定成功
        } catch (Exception e) {
            log.error("Failed to start server", e);
            boss.shutdownGracefully();
            worker.shutdownGracefully();
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public void disconnectClient(String channelId) {
        // 断开特定的连接
        Channel channel = channelMap.get(channelId);
        if (channel != null && channel.isActive()) {
            channel.close().addListener((ChannelFutureListener) future -> {
                if (future.isSuccess()) {
                    log.debug("Disconnected client with ID: {}", channelId);
                    channelMap.remove(channelId);
                } else {
                    log.error("Failed to disconnect client with ID: {}", channelId, future.cause());
                }
            });
        }
    }

    public void write(String channelKey) {
        if (channelMap.containsKey(channelKey)) {
            Channel channel = channelMap.get(channelKey);
            if (channel.isActive()) {
                ByteBuf buffer = Unpooled.copiedBuffer("这是服务端消息", java.nio.charset.StandardCharsets.UTF_8);
                channel.writeAndFlush(buffer).addListener((ChannelFutureListener) future -> {
                    if (future.isSuccess()) {
                        log.debug("Message sent to client with ID: {}", channelKey);
                    } else {
                        log.error("Failed to send message to client with ID: {}", channelKey, future.cause());
                    }
                });
            } else {
                log.warn("Channel with ID {} is not active", channelKey);
            }
        } else {
            log.warn("No channel found with ID: {}", channelKey);
        }
    }

    // 打印连接列表
    public void printConnectMap() {
        channelMap.forEach((k, v) -> {
            log.debug("{} : {}", k, v);
            write(k);
        });
    }
}
